using Lazy.Captcha.Core;
using Lazy.Captcha.Core.Generator;
using Lazy.Captcha.Core.Generator.Image;
using Lazy.Captcha.Core.Generator.Image.Option;
using Lazy.Captcha.Core.RateLimit;
using Microsoft.AspNetCore.Mvc;
using SkiaSharp;

namespace Sample.NetCore.Controllers
{
    [Route("captcha")]
    [ApiController]
    public class CaptchaController : Controller
    {
        private readonly ICaptcha _captcha;

        public CaptchaController(ICaptcha captcha)
        {
            _captcha = captcha;
        }

        /// <summary>
        /// 获取客户端真实IP地址（支持代理）
        /// </summary>
        /// <returns></returns>
        private string GetClientIpAddress()
        {
            // 按优先级检查各种可能包含真实IP的请求头
            var ipHeaders = new[]
            {
                "X-Forwarded-For",      // 标准的代理头
                "X-Real-IP",            // Nginx常用
                "X-Client-IP",          // Apache常用
                "X-Forwarded",          // 非标准但常见
                "X-Cluster-Client-IP",  // 集群环境
                "Forwarded-For",        // RFC 7239之前的标准
                "Forwarded"             // RFC 7239标准
            };

            foreach (var header in ipHeaders)
            {
                var headerValue = HttpContext.Request.Headers[header].FirstOrDefault();
                if (!string.IsNullOrEmpty(headerValue))
                {
                    // X-Forwarded-For 可能包含多个IP，格式：client, proxy1, proxy2
                    // 取第一个IP作为客户端IP
                    var firstIp = headerValue.Split(',')[0].Trim();
                    if (IsValidIpAddress(firstIp))
                    {
                        return firstIp;
                    }
                }
            }

            // 如果没有找到代理头中的IP，使用连接的远程IP
            var remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString();
            if (!string.IsNullOrEmpty(remoteIp) && IsValidIpAddress(remoteIp))
            {
                return remoteIp;
            }

            return "unknown";
        }

        /// <summary>
        /// 验证IP地址格式是否有效
        /// </summary>
        /// <param name="ipAddress">IP地址字符串</param>
        /// <returns></returns>
        private bool IsValidIpAddress(string ipAddress)
        {
            if (string.IsNullOrWhiteSpace(ipAddress))
                return false;

            // 排除明显无效的值
            if (ipAddress.Equals("unknown", StringComparison.OrdinalIgnoreCase) ||
                ipAddress.Equals("localhost", StringComparison.OrdinalIgnoreCase) ||
                ipAddress.Equals("127.0.0.1") ||
                ipAddress.Equals("::1"))
            {
                return false;
            }

            // 使用.NET内置方法验证IP格式
            return System.Net.IPAddress.TryParse(ipAddress, out _);
        }

        [HttpGet]
        public IActionResult Captcha(string id)
        {
            var info = _captcha.Generate(id);
            // 可能会有多个验证码且过期时间不一致，可能存在多线程问题，建议使用默认设置。见https://gitee.com/pojianbing/lazy-captcha/issues/I4XHGM
            //var info = _captcha.Generate(id,120);
            var stream = new MemoryStream(info.Bytes);
            return File(stream, "image/gif");
        }

        /// <summary>
        /// 演示时使用HttpGet传参方便，生产环境请使用Post
        /// </summary>
        [HttpGet("validate")]
        public bool Validate(string id, string code)
        {
            return _captcha.Validate(id, code);
        }

        /// <summary>
        /// 一次性验证码校验（https://gitee.com/pojianbing/lazy-captcha/issues/I4XHGM）
        /// 演示时使用HttpGet传参方便，生产环境请使用Post
        /// </summary>
        [HttpGet("validate2")]
        public bool Validate2(string id, string code)
        {
            return _captcha.Validate(id, code, false);
        }


        /// <summary>
        /// 不使用注入方式，可以灵活配置是否给前端动态展示
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"></param>
        /// <param name="font"></param>
        /// <returns></returns>
        [HttpGet("dynamic")]
        public IActionResult DynamicCaptcha(string id, string type, string font, bool textBold = true)
        {
            var captchaService = CaptchaServiceBuilder
              .New()
              .Width(98)
              .Height(35)
              .FontSize(26)
              .CaptchaType(Enum.Parse<CaptchaType>(type))
              .FontFamily(DefaultFontFamilies.GetFontFamily(font))
              .InterferenceLineCount(2)
              .Animation(false)
              .TextBold(textBold)
              .BackgroundColor(SKColor.Parse("#00ffffff"))
              .Build();
            var info = captchaService.Generate(id);
            var stream = new MemoryStream(info.Bytes);
            return File(stream, "image/gif");
        }

        /// <summary>
        /// 生成静态验证码图片
        /// </summary>
        /// <returns></returns>
        [HttpGet("image")]
        public IActionResult Image()
        {
            var imageGenerator = new DefaultCaptchaImageGenerator();
            var imageGeneratorOption = new CaptchaImageGeneratorOption()
            {
                // 字体颜色
                ForegroundColors = DefaultColors.Colors
            };
            var bytes = imageGenerator.Generate("hello", imageGeneratorOption);
            var stream = new MemoryStream(bytes);
            return File(stream, "image/gif");
        }

        /// <summary>
        /// 生成验证码（带频率限制）- 基于IP地址限制
        /// </summary>
        /// <param name="id">验证码ID</param>
        /// <returns></returns>
        [HttpGet("rate-limit")]
        public IActionResult CaptchaWithRateLimit(string id)
        {
            try
            {
                // 获取客户端真实IP地址作为频率限制键（支持代理）
                var clientIp = GetClientIpAddress();
                var rateLimitKey = clientIp.ToRateLimitKey();

                // 使用频率限制生成验证码
                var info = _captcha.GenerateWithRateLimit(id, rateLimitKey);
                var stream = new MemoryStream(info.Bytes);
                return File(stream, "image/gif");
            }
            catch (RateLimitExceededException ex)
            {
                // 返回429状态码表示频率限制超出
                return StatusCode(429, new
                {
                    error = "频率限制超出",
                    message = ex.Message,
                    remainingRequests = ex.RemainingRequests,
                    resetTime = ex.ResetTime,
                    windowSeconds = ex.WindowSeconds,
                    maxRequests = ex.MaxRequests,
                    clientIp = GetClientIpAddress() // 返回检测到的客户端IP用于调试
                });
            }
        }

        /// <summary>
        /// 生成验证码（带频率限制）- 基于用户ID限制
        /// </summary>
        /// <param name="id">验证码ID</param>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        [HttpGet("rate-limit-user")]
        public IActionResult CaptchaWithUserRateLimit(string id, string userId)
        {
            try
            {
                // 使用用户ID作为频率限制键
                var rateLimitKey = RateLimitKeyStrategy.UserId.GenerateRateLimitKey(userId: userId);

                // 使用频率限制生成验证码
                var info = _captcha.GenerateWithRateLimit(id, rateLimitKey);
                var stream = new MemoryStream(info.Bytes);
                return File(stream, "image/gif");
            }
            catch (RateLimitExceededException ex)
            {
                return StatusCode(429, new
                {
                    error = "用户频率限制超出",
                    message = ex.Message,
                    remainingRequests = ex.RemainingRequests,
                    resetTime = ex.ResetTime,
                    windowSeconds = ex.WindowSeconds,
                    maxRequests = ex.MaxRequests
                });
            }
        }

        /// <summary>
        /// 检查频率限制状态
        /// </summary>
        /// <param name="userId">用户ID（可选）</param>
        /// <returns></returns>
        [HttpGet("rate-limit-status")]
        public IActionResult CheckRateLimitStatus(string? userId = null)
        {
            try
            {
                string rateLimitKey;
                if (!string.IsNullOrEmpty(userId))
                {
                    // 基于用户ID检查
                    rateLimitKey = RateLimitKeyStrategy.UserId.GenerateRateLimitKey(userId: userId);
                }
                else
                {
                    // 基于IP地址检查（支持代理）
                    var clientIp = GetClientIpAddress();
                    rateLimitKey = clientIp.ToRateLimitKey();
                }

                var result = _captcha.CheckRateLimit(rateLimitKey);

                return Ok(new
                {
                    isAllowed = result.IsAllowed,
                    remainingRequests = result.RemainingRequests,
                    resetTime = result.ResetTime,
                    windowSeconds = result.WindowSeconds,
                    maxRequests = result.MaxRequests,
                    key = result.Key,
                    secondsUntilReset = result.GetSecondsUntilReset()
                });
            }
            catch (Exception ex)
            {
                return BadRequest(new { error = ex.Message });
            }
        }

        /// <summary>
        /// 生成验证码（带频率限制）- 基于自定义键限制（如设备ID）
        /// </summary>
        /// <param name="id">验证码ID</param>
        /// <param name="deviceId">设备ID</param>
        /// <returns></returns>
        [HttpGet("rate-limit-device")]
        public IActionResult CaptchaWithDeviceRateLimit(string id, string deviceId)
        {
            try
            {
                // 使用设备ID作为自定义频率限制键
                var rateLimitKey = RateLimitKeyStrategy.Custom.GenerateRateLimitKey(customKey: deviceId);

                // 使用频率限制生成验证码
                var info = _captcha.GenerateWithRateLimit(id, rateLimitKey);
                var stream = new MemoryStream(info.Bytes);
                return File(stream, "image/gif");
            }
            catch (RateLimitExceededException ex)
            {
                return StatusCode(429, new
                {
                    error = "设备频率限制超出",
                    message = ex.Message,
                    remainingRequests = ex.RemainingRequests,
                    resetTime = ex.ResetTime,
                    windowSeconds = ex.WindowSeconds,
                    maxRequests = ex.MaxRequests,
                    deviceId = deviceId
                });
            }
        }
    }
}